package com.ruoyi.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.system.domain.RecZmPaperManagementD;
import com.ruoyi.system.domain.RecordTable;
import com.ruoyi.system.domain.RecordType;
import com.ruoyi.system.domain.vo.TypeTreeSelect;
import com.ruoyi.system.mapper.RecordManageMapper;
import com.ruoyi.system.mapper.RecordTableMapper;
import com.ruoyi.system.mapper.RecordTypeMapper;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.service.IRecordTypeService;
import com.ruoyi.system.service.ISysRoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.validation.Validator;
import java.security.Permission;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 档案分类Service业务层处理
 *
 * @author admin
 * @date 2022-02-19
 */
@Service
public class RecordTypeServiceImpl implements IRecordTypeService {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected Validator validator;
    @Autowired
    private RecordTypeMapper recordTypeMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private RecordManageMapper manageMapper;

    @Autowired
    private RecordTableMapper recordTableMapper;

    @Autowired
    private SysConfigServiceImpl sysConfigService;

    /**
     * 查询档案分类
     *
     * @param typeId 档案分类主键
     * @return 档案分类
     */
    @Override
    public RecordType selectRecordTypeByTypeId(String typeId) {
        return recordTypeMapper.selectRecordTypeByTypeId(typeId);
    }

    /**
     * 查询档案分类列表
     *
     * @param recordType 档案分类
     * @return 档案分类
     */
    @Override
    public List<RecordType> selectRecordTypeList(RecordType recordType) {
        // 规则：判断是二级部门还是三级部门，还是三级以下的部门
        // 1.管理员，通过所有
        // 2.如果是一级，二级部门，查看所有档案分类
        // 3.如果是三级部门及一下，按祖籍往下查看
        SysDept dept = sysDeptMapper.selectDeptById(SecurityUtils.getDeptId());
        String ancestors = dept.getAncestors();
        String[] ans = ancestors.split(","); // 以逗号切割字符串
        int length = ans.length;
        // 角色集合
        List<SysRole> roleList = SecurityUtils.getLoginUser().getUser().getRoles();
        Boolean isAdmin = false;
        for(SysRole role: roleList){
            if(sysConfigService.selectConfigByKey("admin").equals(role.getRoleKey()) || sysConfigService.selectConfigByKey("record_admin").equals(role.getRoleKey())){
                isAdmin = true;
                break;
            }
        }
        if(isAdmin){
            // 管理员，通过
        }else if(length == 1 || length == 2){
            recordType.setDeptId(null);
        }else{
            recordType.setDeptId(SecurityUtils.getDeptId());
        }
        return recordTypeMapper.selectRecordTypeList(recordType);
    }

    /**
     * 新增档案分类
     *
     * @param recordType 档案分类
     * @return 结果
     */
    @Override
    @Transactional
    public int insertRecordType(RecordType recordType) {
        // 设置回滚点
        Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
        recordType.setCreateTime(DateUtils.getNowDate());
        recordType.setCreateBy(SecurityUtils.getUsername());
        RecordType info = recordTypeMapper.selectRecordTypeByTypeId(recordType.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (info != null && !UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
            throw new ServiceException("类别停用，不允许新增");
        }
        if (info != null) {
            recordType.setAncestors(info.getAncestors() + "," + recordType.getParentId());
        } else {
            recordType.setAncestors("0"); // 根目录祖籍id统一设置为0
        }
        try {
            int i = recordTypeMapper.insertRecordType(recordType);
            // 循环插入中间表
            for(String deptId: recordType.getDeptIds()){
                if(StringUtils.isNotEmpty(deptId)){
                    String sql = "insert into record_type_dept ( dept_id, type_id ) values( #{deptId}, #{typeId} )";
                    Map<String, Object> map = new HashMap<>();
                    map.put("deptId", deptId);
                    map.put("typeId", recordType.getTypeId());
                    map.put("sql", sql);
                    manageMapper.insertRecordManage(map);
                }
            }
            return i;
        } catch (Exception e) {
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
            throw new ServiceException("插入失败！" + e);
        }
    }

    /**
     * 修改档案分类
     *
     * @param recordType 档案分类
     * @return 结果
     */
    @Override
    @Transactional
    public int updateRecordType(RecordType recordType) {
        // 设置回滚点
        Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
        try {
            // 如果存在数据，则先清空，再插入
            Map<String, Object> map = new HashMap<>();
            map.put("typeId", recordType.getTypeId());
            String sql = "select * from record_type_dept where type_id = #{typeId}";
            map.put("sql", sql);
            List<Map<String, Object>> mList =  manageMapper.selectRecordManageList(map);
            if(mList.size() > 0){
                sql = "delete from record_type_dept where type_id = #{typeId}";
                map.put("sql", sql);
                manageMapper.deleteRecordManage(map);
            }
            // 循环插入中间表
            for(String deptId: recordType.getDeptIds()){
                String sqlNew = "insert into record_type_dept ( dept_id, type_id ) values( #{deptId}, #{typeId} )";
                Map<String, Object> mapNew = new HashMap<>();
                mapNew.put("deptId", deptId);
                mapNew.put("typeId", recordType.getTypeId());
                mapNew.put("sql", sqlNew);
                manageMapper.insertRecordManage(mapNew);
            }
            // 如果已建表，不允许修改建表标识
            String oldFlag = recordTypeMapper.selectRecordTypeByTypeId(recordType.getTypeId()).getTbFlag();
            if(!oldFlag.equals(recordType.getTbFlag())){
                RecordTable recordTable = new RecordTable();
                recordTable.setTypeId(recordType.getTypeId());
                int i = recordTableMapper.selectRecordTableList(recordTable).size();
                if(i > 0){
                    throw new ServiceException("该分类已建表，不允许修改建表flag！");
                }
            }
            // 修改表
            recordType.setUpdateTime(DateUtils.getNowDate());
            if(recordType.getTypeId().equals(recordType.getParentId())){
                throw new ServiceException("禁止分类自挂，请重新选择父级分类！");
            }
            return recordTypeMapper.updateRecordType(recordType);
        } catch (Exception e) {
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
            throw new ServiceException("修改失败！" + e);
        }
    }

    /**
     * 批量删除档案分类
     *
     * @param typeIds 需要删除的档案分类主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRecordTypeByTypeIds(String[] typeIds) {
        // 设置回滚点
        Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
        // 1.删除中间表
        // 2.删除档案分类
        try {
            for(String typeId: typeIds){
                String sql = "delete from record_type_dept where type_id = #{typeId}";
                Map<String, Object> map = new HashMap<>();
                map.put("typeId", typeId);
                map.put("sql", sql);
                manageMapper.deleteRecordManage(map);
            }
            return recordTypeMapper.deleteRecordTypeByTypeIds(typeIds);
        } catch (Exception e) {
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
            throw new ServiceException("删除失败！" + e);
        }
    }

    /**
     * 删除档案分类信息
     *
     * @param typeId 档案分类主键
     * @return 结果
     */
    @Override
    public int deleteRecordTypeByTypeId(String typeId) {
        return recordTypeMapper.deleteRecordTypeByTypeId(typeId);
    }


    /**
     * 构建前端所需要下拉树结构
     *
     * @param types 分类列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TypeTreeSelect> buildRecordTypeTreeSelect(List<RecordType> types) {
        List<RecordType> typeTrees = buildTypeTree(types);
        return typeTrees.stream().map(TypeTreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 查询flag档案分类
     *
     * @param  typeId
     * @return 档案分类
     */
    @Override
    public RecordType selectFlagType(String typeId) {
        // 1.如果尾部有建表flag，直接返回。
        // 2.否则循环查找上级第一个flag分类
        RecordType recordType = new RecordType();
        RecordType recordOld = recordTypeMapper.selectRecordTypeByTypeId(typeId);
        String ancestors = recordOld.getAncestors();
        String[] ans = ancestors.split(","); // 以逗号切割字符串
        int length = ans.length;
        String fullAnces = null;
        // 查询flag
        if(StringUtils.isNotNull(recordOld.getTbFlag()) && "1".equals(recordOld.getTbFlag())){
            return recordOld;
        }

        for(int i = length - 1; i >= 0; i--){
            recordType = recordTypeMapper.selectRecordTypeByTypeId(ans[i]);
            if(StringUtils.isNotNull(recordType) && "1".equals(recordType.getTbFlag())){
                return recordType;
            }
        }
        throw new ServiceException("档案树建表flag不能为空！");
    }

    /**
     * 构建前端所需要树结构
     *
     * @param types 类型列表
     * @return 树结构列表
     */
    public List<RecordType> buildTypeTree(List<RecordType> types) {
        List<RecordType> returnList = new ArrayList<RecordType>();
        List<String> tempList = new ArrayList<String>();
        for (RecordType type : types) {
            tempList.add(type.getTypeId());
        }
        for (RecordType type : types) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(type.getParentId())) {
                recursionFn(types, type);
                returnList.add(type);
            }
        }
        if (returnList.isEmpty()) {
            returnList = types;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<RecordType> list, RecordType t) {
        // 得到子节点列表
        List<RecordType> childList = getChildList(list, t);
        t.setChildren(childList);
        for (RecordType tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<RecordType> getChildList(List<RecordType> list, RecordType t) {
        List<RecordType> tlist = new ArrayList<RecordType>();
        Iterator<RecordType> it = list.iterator();
        while (it.hasNext()) {
            RecordType n = (RecordType) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().equals(t.getTypeId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<RecordType> list, RecordType t) {
        return getChildList(list, t).size() > 0;
    }

    /**
     * 数据导入
     */
    @Override
    @Transactional
    public String importFile(List<RecordType> fileList) {
        // 设置回滚点
        Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
        if (CollUtil.isEmpty(fileList)) {
            throw new ServiceException("导入文件数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (RecordType file : fileList) {
            try {
                BeanValidators.validateWithException(validator, file);
                file.setCreateBy(SecurityUtils.getUsername());
                // 字符串转数组
                List<String> deptIds = new ArrayList<>();
                for (String str: file.getDeptIdStr().split(",")){
                    deptIds.add(str);
                }
                file.setDeptIds(deptIds);
                this.insertRecordType(file);
                successNum++;
                successMsg.append("<br/>" + successNum + "、档案分类 " + file.getTypeName() + " 导入成功");
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、文件 " + file.getTypeName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
                //手工回滚异常
                TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }
}
